home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume22 / pathalias10 / part01 next >
Encoding:
Internet Message Format  |  1990-06-07  |  51.6 KB

  1. Subject:  v22i109:  Pathalias, version 10, Part01/03
  2. Newsgroups: comp.sources.unix
  3. Approved: rsalz@uunet.UU.NET
  4. X-Checksum-Snefru: ed2e8fbf 9221e8c1 b0d37b5e 0970e124
  5.  
  6. Submitted-by: peter honeyman <honey@citi.umich.edu>
  7. Posting-number: Volume 22, Issue 109
  8. Archive-name: pathalias10/part01
  9.  
  10. [ I FTP'd this from peter's machine and am posting it because the version9
  11.   hiccups on the maps.  After this, I'm off to Usenix and a couple of days
  12.   of vacation.  See you in Anaheim, or electronically in a week and a half.
  13.   --r$  ]
  14.  
  15. Pathalias reads the map data after it has been unpacked from comp.mail.maps,
  16. and generates the "lowest-cost" routes from one host to all other hosts in
  17. the maps.
  18.  
  19. #! /bin/sh
  20. # This is a shell archive.  Remove anything before this line, then feed it
  21. # into a shell via "sh file" or similar.  To overwrite existing files,
  22. # type "sh file -c".
  23. # The tool that generated this appeared in the comp.sources.unix newsgroup;
  24. # send mail to comp-sources-unix@uunet.uu.net if you want that tool.
  25. # Contents:  README arpatxt.c mapit.c mem.c pathalias.8
  26. # Wrapped by rsalz@litchi.bbn.com on Fri Jun  8 09:25:19 1990
  27. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  28. echo If this archive is complete, you will see the following message:
  29. echo '          "shar: End of archive 1 (of 3)."'
  30. if test -f 'README' -a "${1}" != "-c" ; then 
  31.   echo shar: Will not clobber existing file \"'README'\"
  32. else
  33.   echo shar: Extracting \"'README'\" \(1156 characters\)
  34.   sed "s/^X//" >'README' <<'END_OF_FILE'
  35. XFrom citi!honey Sun Oct  4 23:30 EDT 1987
  36. XDate: 04 Oct 1987 23:30 EDT
  37. XFrom: honey@citi.umich.edu
  38. XTo: whom it may concern
  39. XSubject: pathalias compilation instructions
  40. X
  41. Xedit config.h
  42. Xmake
  43. X
  44. Xif getopt is undefined, obtain a copy from usenet group
  45. Xcomp.sources.unix and adjust Makefile.
  46. X
  47. Xpathalias input is regularly published in usenet group comp.mail.maps.
  48. X
  49. X    peter
  50. X
  51. Xps:  pathalias, written by steve bellovin and peter honeyman, is in the
  52. X     public domain, and may be used by any person or organization, in
  53. X     any way and for any purpose.
  54. X
  55. Xpps:  There is no warranty of merchantability nor any warranty of fit-
  56. X      ness for a particular purpose nor any other warranty, either ex-
  57. X      press or implied, as to the accuracy of the enclosed materials or
  58. X      as to their suitability for any particular purpose.  Accordingly,
  59. X      the authors assume no responsibility for their use by the recipi-
  60. X      ent.   Further, the authors assume no obligation to furnish any
  61. X      assistance of any kind whatsoever, or to furnish any additional
  62. X      information or documentation.  This paragraph was copied without
  63. X      permission from an old crypt(1) man page.
  64. END_OF_FILE
  65.   if test 1156 -ne `wc -c <'README'`; then
  66.     echo shar: \"'README'\" unpacked with wrong size!
  67.   fi
  68.   # end of 'README'
  69. fi
  70. if test -f 'arpatxt.c' -a "${1}" != "-c" ; then 
  71.   echo shar: Will not clobber existing file \"'arpatxt.c'\"
  72. else
  73.   echo shar: Extracting \"'arpatxt.c'\" \(13330 characters\)
  74.   sed "s/^X//" >'arpatxt.c' <<'END_OF_FILE'
  75. X#ifndef lint
  76. Xstatic char *sccsid = "@(#)arpatxt.c    9.4 88/09/21";
  77. X#endif
  78. X
  79. X/*
  80. X * convert hosts.txt into pathalias format.
  81. X *
  82. X * alias rule: "host.dom.ain,nickname.arpa,..." -> host = nickname, ...
  83. X */
  84. X
  85. X/* remove the next line for standard or research unix */
  86. X#define BSD
  87. X
  88. X#ifdef BSD
  89. X#define strchr index
  90. X#endif /* BSD */
  91. X
  92. X#include <stdio.h>
  93. X#include <ctype.h>
  94. X
  95. X/* imports */
  96. Xextern char *re_comp(), *malloc(), *strchr(), *calloc();
  97. Xextern char *gets(), *strcpy(), *fgets();
  98. Xextern FILE *fopen();
  99. X
  100. Xtypedef struct node node;
  101. X
  102. Xstruct node {
  103. X    node *child;    /* subdomain or member host */
  104. X    node *parent;    /* parent domain */
  105. X    node *next;    /* sibling in domain tree or host list */
  106. X    char *name;    /* host name */
  107. X    node *alias;    /* list of aliases */
  108. X    node *bucket;
  109. X    node *gateway;
  110. X    int  flag;
  111. X};
  112. X
  113. Xnode *Top;
  114. Xint Atflag, Fflag, Iflag, Vflag;
  115. Xchar *DotArpa = ".ARPA";
  116. Xchar Fname[256], *Fstart;
  117. X
  118. Xnode *newnode(), *find();
  119. Xchar *strsave(), *lowercase();
  120. Xvoid crcinit();
  121. Xlong fold();
  122. XFILE *mkfile();
  123. Xint insert();
  124. X
  125. X#define ISADOMAIN(n) ((n) && *((n)->name) == '.')
  126. X
  127. X/* for node.flag */
  128. X#define COLLISION 1
  129. X
  130. X/* for formatprint() */
  131. X#define PRIVATE        0
  132. X#define HOSTS        1
  133. X#define SUBDOMAINS    2
  134. X
  135. X/* for usage() */
  136. X#define USAGE "usage: %s [-i@] [-g gateway] [-p privatefile] [-f | -d directory] [file ...]\n"
  137. X
  138. Xmain(argc, argv)
  139. X    char **argv;
  140. X{    int c;
  141. X    char *progname;
  142. X    extern char *optarg;
  143. X    extern int optind;
  144. X
  145. X    if ((progname = strchr(argv[0], '/')) != 0)
  146. X        progname++;
  147. X    else
  148. X        progname = argv[0];
  149. X    crcinit();
  150. X
  151. X    Top = newnode();    /* needed for adding gateways */
  152. X    while ((c = getopt(argc, argv, "d:fg:ip:v@")) != EOF)
  153. X        switch(c) {
  154. X        case 'd':
  155. X            strcpy(Fname, optarg);
  156. X            break;
  157. X        case 'f':    /* filter mode -- write on stdout */
  158. X            Fflag++;
  159. X            break;
  160. X        case 'g':
  161. X            gateway(optarg);
  162. X            break;
  163. X        case 'i':
  164. X            Iflag++;
  165. X            break;
  166. X        case 'p':
  167. X            readprivates(optarg);
  168. X            break;
  169. X        case 'v':
  170. X            Vflag++;
  171. X            break;
  172. X        case '@':
  173. X            Atflag++;
  174. X            break;
  175. X        default:
  176. X            usage(progname);
  177. X        }
  178. X
  179. X    if (Fflag && *Fname)
  180. X        usage(progname);
  181. X    if (Iflag)
  182. X        (void) lowercase(DotArpa);
  183. X    if (Top->gateway == 0)
  184. X        fprintf(stderr, "%s: warning: no gateway to top level domains\n", progname);
  185. X
  186. X    Fstart = Fname + strlen(Fname);
  187. X    if (Fstart != Fname) {
  188. X        *Fstart++ = '/';
  189. X        *Fstart = 0;
  190. X    }
  191. X    /* should do the mkdir here instead of the shell script ...*/
  192. X        
  193. X    Top->name = "internet";
  194. X    if (optind == argc)
  195. X        scan();
  196. X    else for ( ; optind < argc; optind++) {
  197. X        if (freopen(argv[optind], "r", stdin) == 0) {
  198. X            perror(argv[optind]);
  199. X            continue;
  200. X        }
  201. X        scan();
  202. X    }
  203. X    setuniqflag(Top);    /* look for and mark collisions */
  204. X    hashanalyze();        /* check hash algorithm performance */
  205. X    merge();        /* make unique domain names */
  206. X    dump(Top);        /* print */
  207. X    return 0;
  208. X}
  209. X
  210. Xscan()
  211. X{    static first;
  212. X    char buf0[BUFSIZ], buf1[BUFSIZ], buf2[BUFSIZ];
  213. X
  214. X    if (first++ == 0)
  215. X        (void) re_comp("^HOST.*SMTP");
  216. X    while (gets(buf0) != 0) {
  217. X        if (re_exec(buf0) == 0)
  218. X            continue;
  219. X        if (sscanf(buf0, "HOST : %[^:] : %[^: ]", buf1, buf2) != 2)
  220. X            continue;
  221. X        if (Iflag)
  222. X            (void) lowercase(buf2);
  223. X        if (insert(buf2) != 0)
  224. X            fprintf(stderr, "input error: %s\n", buf0);
  225. X    }
  226. X}
  227. X/*
  228. X * format of private file:
  229. X *    one per line, optionally followed by white space and comments
  230. X *    line starting with # is comment
  231. X */
  232. Xreadprivates(pfile)
  233. X    char *pfile;
  234. X{    FILE *f;
  235. X    node *n;
  236. X    char buf[BUFSIZ], *bptr;
  237. X
  238. X    if ((f = fopen(pfile, "r")) == 0) {
  239. X        perror(pfile);
  240. X        return;
  241. X    }
  242. X    while (fgets(buf, BUFSIZ, f) != 0) {
  243. X        if (*buf == '#')
  244. X            continue;
  245. X        if ((bptr = strchr(buf, ' ')) != 0)
  246. X            *bptr = 0;
  247. X        if ((bptr = strchr(buf, '\t')) != 0)
  248. X            *bptr = 0;
  249. X        if (*buf == 0)
  250. X            continue;
  251. X        n = newnode();
  252. X        n->name = strsave(buf);
  253. X        hash(n);
  254. X    }
  255. X    (void) fclose(f);
  256. X}
  257. Xusage(progname)
  258. X    char *progname;
  259. X{
  260. X    fprintf(stderr, USAGE, progname);
  261. X    exit(1);
  262. X}
  263. X
  264. Xdumpgateways(ndom, f)
  265. X    node *ndom;
  266. X    FILE *f;
  267. X{    node *n;
  268. X
  269. X    for (n = ndom->gateway; n; n = n->next) {
  270. X        fprintf(f, "%s ", n->name);
  271. X        if (Atflag)
  272. X            putc('@', f);
  273. X        fprintf(f, "%s(%s)\t# gateway\n", ndom->name,
  274. X                ndom == Top ? "DEDICATED" : "LOCAL");
  275. X    }
  276. X}
  277. X
  278. Xgateway(buf)
  279. X    char *buf;
  280. X{    node *n, *dom;
  281. X    char *dot;
  282. X
  283. X    dot = strchr(buf, '.');
  284. X    if (dot) {
  285. X        dom = find(dot);
  286. X        *dot = 0;
  287. X    } else
  288. X        dom = Top;
  289. X
  290. X    n = newnode();
  291. X    n->name = strsave(buf);
  292. X    n->next = dom->gateway;
  293. X    dom->gateway = n;
  294. X}
  295. X    
  296. Xint
  297. Xinsert(buf)
  298. X    char *buf;
  299. X{    char host[BUFSIZ], *hptr, *dot;
  300. X    node *n;
  301. X
  302. X    for (hptr = host; *hptr = *buf++; hptr++)
  303. X        if (*hptr == ',')
  304. X            break;
  305. X
  306. X    if (*hptr == ',')
  307. X        *hptr = 0;
  308. X    else
  309. X        buf = 0;    /* no aliases */
  310. X
  311. X    if ((dot = strchr(host, '.')) == 0)
  312. X        return 1;    /* can't happen */
  313. X    
  314. X    if (strcmp(dot, DotArpa) == 0)
  315. X        buf = 0;        /* no aliases */
  316. X
  317. X    n = find(dot);
  318. X    *dot = 0;
  319. X
  320. X    addchild(n, host, buf);
  321. X    return 0;
  322. X}
  323. X
  324. Xnode *
  325. Xfind(domain)
  326. X    char *domain;
  327. X{    char *dot;
  328. X    node *parent, *child;
  329. X
  330. X    if (domain == 0)
  331. X        return Top;
  332. X    if ((dot = strchr(domain+1, '.')) != 0) {
  333. X        parent = find(dot);
  334. X        *dot = 0;
  335. X    } else
  336. X        parent = Top;
  337. X
  338. X    for (child = parent->child; child; child = child->next)
  339. X        if (strcmp(domain, child->name) == 0)
  340. X            break;
  341. X    if (child == 0) {
  342. X        child = newnode();
  343. X        child->next = parent->child;
  344. X        parent->child = child;
  345. X        child->parent = parent;
  346. X        child->name = strsave(domain);
  347. X    }
  348. X    return child;
  349. X}
  350. X
  351. Xnode *
  352. Xnewnode()
  353. X{
  354. X    node *n;
  355. X
  356. X    if ((n = (node *) calloc(1, sizeof(node))) == 0)
  357. X        abort();
  358. X    return n;
  359. X}
  360. X
  361. Xchar *
  362. Xstrsave(buf)
  363. X    char *buf;
  364. X{    char *mstr;
  365. X
  366. X    if ((mstr = malloc(strlen(buf)+1)) == 0)
  367. X        abort();
  368. X    strcpy(mstr, buf);
  369. X    return mstr;
  370. X}
  371. X
  372. Xaddchild(n, host, aliases)
  373. X    node *n;
  374. X    char *host, *aliases;
  375. X{    node *child;
  376. X
  377. X    /* check for dups?  nah! */
  378. X    child = newnode();
  379. X    child->name = strsave(host);
  380. X    child->parent = n;
  381. X    child->next = n->child;
  382. X    makealiases(child, aliases);
  383. X    n->child = child;
  384. X}
  385. X
  386. X/* yer basic tree walk to make output */
  387. Xdump(n)
  388. X    node *n;
  389. X{    node *child;
  390. X    FILE *f;
  391. X    int privates;
  392. X
  393. X    /* sanity check */
  394. X    if (n != Top && ! ISADOMAIN(n))
  395. X        abort();
  396. X
  397. X    f = mkfile(n);        /* prepare the output file */
  398. X    privates = domprint(n, f);        /* print this domain */
  399. X    dumpgateways(n, f);    /* print any gateways to this domain */
  400. X    if (privates || n == Top)
  401. X        fputs("private {}\n", f);    /* end scope of privates */
  402. X    if (Fflag)
  403. X        putc('\n', f);
  404. X    else
  405. X        (void) fclose(f);
  406. X    for (child = n->child; child; child = child->next)
  407. X        if (child->child)
  408. X            dump(child);
  409. X}
  410. X
  411. Xqcmp(a, b)
  412. X    node **a, **b;
  413. X{
  414. X    return strcmp((*a)->name, (*b)->name);
  415. X}
  416. X
  417. Xdomprint(n, f)
  418. X    node *n;
  419. X    FILE *f;
  420. X{    node *table[8191], *child, *alias;
  421. X    char *cost = 0;
  422. X    int nelem, i, privates = 0;
  423. X
  424. X    /*
  425. X     * dump private definitions.  
  426. X     * sort hosts and aliases for pretty output.
  427. X     */
  428. X    if (n != Top) {
  429. X        i = 0;
  430. X        for (child = n->child; child; child = child->next) {
  431. X            table[i++] = child;
  432. X            for (alias = child->alias; alias; alias = alias->next)
  433. X                table[i++] = alias;
  434. X        }
  435. X
  436. X        qsort((char *) table, i, sizeof(table[0]), qcmp);
  437. X        privates = formatprint(f, table, i, PRIVATE, "private", cost);
  438. X    }
  439. X
  440. X    /* dump domains and aliases, sorted for pretty output */
  441. X    i = 0;
  442. X    for (child = n->child; child; child = child->next)
  443. X        table[i++] = child;
  444. X    qsort((char *) table, i, sizeof(table[0]), qcmp);
  445. X
  446. X    /* cost is DEDICATED for hosts in top-level domains, LOCAL o.w. */
  447. X    if (n->parent == Top && strchr(n->name + 1, '.') == 0)
  448. X        cost = "DEDICATED";
  449. X    else
  450. X        cost = "LOCAL";
  451. X
  452. X    (void) formatprint(f, table, i, HOSTS, n->name, cost);
  453. X    (void) formatprint(f, table, i, SUBDOMAINS, n->name, "0");
  454. X
  455. X    /* dump aliases */
  456. X    nelem = i;
  457. X    for (i = 0; i < nelem; i++) {
  458. X        if ((alias = table[i]->alias) == 0)
  459. X            continue;
  460. X        fprintf(f, "%s = %s", table[i]->name, alias->name);
  461. X        for (alias = alias->next; alias; alias = alias->next)
  462. X            fprintf(f, ", %s", alias->name);
  463. X        putc('\n', f);
  464. X    }
  465. X    return privates;
  466. X}
  467. X
  468. Xint
  469. Xformatprint(f, table, nelem, type, lhs, cost)
  470. X    FILE *f;
  471. X    node **table;
  472. X    char *lhs, *cost;
  473. X{    int i, didprint;
  474. X    char buf[128], *bptr;
  475. X
  476. X    sprintf(buf, "%s%s{" /*}*/, lhs, type == PRIVATE ? " " : " = ");
  477. X    bptr = buf + strlen(buf);
  478. X
  479. X    didprint = 0;
  480. X    for (i = 0; i < nelem; i++) {
  481. X        if (type == PRIVATE && ! (table[i]->flag & COLLISION))
  482. X            continue;
  483. X        else if (type == HOSTS && ISADOMAIN(table[i]) )
  484. X            continue;
  485. X        else if (type == SUBDOMAINS && ! ISADOMAIN(table[i]) )
  486. X            continue;
  487. X
  488. X        if ((bptr - buf) + strlen(table[i]->name) > 69) {
  489. X            *bptr = 0;
  490. X            fprintf(f, "%s\n ", buf);    /* continuation */
  491. X            bptr = buf;
  492. X        }
  493. X        sprintf(bptr, "%s, ", table[i]->name);
  494. X        bptr += strlen(bptr);
  495. X        didprint++;
  496. X    }
  497. X    *bptr = 0;
  498. X
  499. X    if (didprint) {
  500. X        fprintf(f, /*{*/ "%s}", buf);
  501. X        if (type != PRIVATE)
  502. X            fprintf(f, "(%s)", cost);
  503. X        putc('\n', f);
  504. X    }
  505. X    return didprint;
  506. X}
  507. X
  508. XFILE *                
  509. Xmkfile(n)
  510. X    node *n;
  511. X{    node *parent;
  512. X    char *bptr;
  513. X    FILE *f;
  514. X
  515. X    /* build up the domain name in Fname[] */
  516. X    bptr = Fstart;
  517. X    if (n == Top)
  518. X        strcpy(bptr, n->name);
  519. X    else {
  520. X        strcpy(bptr, n->name + 1);    /* skip leading dot */
  521. X        bptr = bptr + strlen(bptr);
  522. X        parent = n->parent;
  523. X        while (ISADOMAIN(parent)) {
  524. X            strcpy(bptr, parent->name);
  525. X            bptr += strlen(bptr);
  526. X            parent = parent->parent;
  527. X        }
  528. X        *bptr = 0;
  529. X    }
  530. X
  531. X    /* get a stream descriptor */
  532. X    if (Fflag) {
  533. X        printf("# %s\n", Fstart);
  534. X        f = stdout;
  535. X    } else {
  536. X#ifndef BSD
  537. X        Fstart[14] = 0;
  538. X#endif
  539. X        if ((f = fopen(Fname, "w")) == 0) {
  540. X            perror(Fname);
  541. X            exit(1);
  542. X        }
  543. X    }
  544. X    if (n == Top)
  545. X        fprintf(f, "private {%s}\ndead {%s}\n", Top->name, Top->name);
  546. X    return f;
  547. X}
  548. X
  549. X/* map to lower case in place.  return parameter for convenience */
  550. Xchar *
  551. Xlowercase(buf)
  552. X    char *buf;
  553. X{    char *str;
  554. X
  555. X    for (str = buf ; *str; str++)
  556. X        if (isupper(*str))
  557. X            *str -= 'A' - 'a';
  558. X    return buf;
  559. X}
  560. X
  561. X/* get the interesting aliases, attach to n->alias */
  562. Xmakealiases(n, line)
  563. X    node *n;
  564. X    char *line;
  565. X{    char *next, *dot;
  566. X    node *a;
  567. X
  568. X    if (line == 0 || *line == 0)
  569. X        return;
  570. X
  571. X    for ( ; line; line = next) {
  572. X        next = strchr(line, ',');
  573. X        if (next)
  574. X            *next++ = 0;
  575. X        if ((dot = strchr(line, '.')) == 0)
  576. X            continue;
  577. X        if (strcmp(dot, DotArpa) != 0)
  578. X            continue;
  579. X        *dot = 0;
  580. X
  581. X        if (strcmp(n->name, line) == 0)
  582. X            continue;
  583. X
  584. X        a = newnode();
  585. X        a->name = strsave(line);
  586. X        a->next = n->alias;
  587. X        n->alias = a;
  588. X    }
  589. X}
  590. X
  591. X/* make unique domain names */
  592. Xmerge()
  593. X{    register node *n;
  594. X
  595. X    for (n = Top->child; n; n = n->next)
  596. X        make_children_unique(n);
  597. X}
  598. X
  599. X/*
  600. X * another recursive tree walk, this time to make unique domain
  601. X * components.
  602. X *
  603. X * for domains like cc.umich.edu and cc.berkeley.edu, it's inaccurate
  604. X * to describe cc as a member of umich.edu or berkeley.edu.  (i.e., the
  605. X * lousy scoping rules for privates don't permit a clean syntax.)  so.
  606. X *
  607. X * to prevent confusion, tack on to any such domain name its parent domain
  608. X * and promote it in the tree.  e.g., make cc.umich and cc.berkeley
  609. X * subdomains of edu.
  610. X */
  611. X
  612. Xmake_children_unique(parent)
  613. X    node *parent;
  614. X{    node *prev, *child, *next;
  615. X    char buf[BUFSIZ];
  616. X
  617. X    prev = 0;
  618. X    for (child = parent->child; child; child = next) {
  619. X        next = child->next;
  620. X
  621. X        /* skip hosts */
  622. X        if (!ISADOMAIN(child)) {
  623. X            prev = child;
  624. X            continue;
  625. X        }
  626. X
  627. X        /*
  628. X         * promote non-unique domain, or any domain with a
  629. X         * gateway.  (the latter get promoted all the way to
  630. X         * top-level.)
  631. X         */
  632. X        if ((child->flag & COLLISION) == 0 && child->gateway == 0) {
  633. X            /*
  634. X             * uninteresting domain.  make its children
  635. X             * unique and bump prev.
  636. X             */
  637. X            make_children_unique(child);
  638. X            prev = child;
  639. X            continue;
  640. X        }
  641. X
  642. X        /*
  643. X         * gateway or dup domain name found.  don't bump
  644. X         * prev: this node is moving up the tree.
  645. X         */
  646. X
  647. X        /* qualify child domain name */
  648. X        sprintf(buf, "%s%s", child->name, parent->name);
  649. X        cfree(child->name);
  650. X        child->name = strsave(buf);
  651. X
  652. X        /* unlink child out of sibling chain */
  653. X        if (prev)
  654. X            prev->next = child->next;
  655. X        else
  656. X            parent->child = child->next;
  657. X
  658. X        /* link child in as peer of parent */
  659. X        child->next = parent->next;
  660. X        parent->next = child;
  661. X        child->parent = parent->parent;
  662. X
  663. X        /*
  664. X         * reset collision flag; may promote again on
  665. X         * return to caller.
  666. X         */
  667. X        child->flag &= ~COLLISION;
  668. X        hash(child);
  669. X    }
  670. X}
  671. X
  672. X/* another recursive tree walk, this time to set the COLLISION bit. */
  673. Xsetuniqflag(n)
  674. X    node *n;
  675. X{    node *child, *alias;
  676. X
  677. X    /* mark this node in the hash table */
  678. X    hash(n);
  679. X    /* mark the aliases of this node */
  680. X    for (alias = n->alias; alias; alias = alias->next)
  681. X        hash(alias);
  682. X    /* recursively mark this node's children */
  683. X    for (child = n->child; child; child = child->next)
  684. X        setuniqflag(child);
  685. X}
  686. X
  687. X#define NHASH 8191        /* must be prime */
  688. Xnode *Htable[NHASH];        /* hash table */
  689. X
  690. Xhash(n)
  691. X    node *n;
  692. X{    node **bucket, *b;
  693. X
  694. X    bucket = Htable + (fold(n->name) % NHASH);
  695. X    for (b = *bucket; b; b = b->bucket)
  696. X        if (strcmp(n->name, b->name) == 0) {
  697. X            b->flag |= COLLISION;
  698. X            n->flag |= COLLISION;
  699. X            return;
  700. X        }
  701. X
  702. X    n->bucket = *bucket;
  703. X    *bucket = n;
  704. X}
  705. X
  706. X/* stolen from pathalias:addnode.c, q.v. */
  707. X#define POLY    0x48000000        /* 31-bit polynomial */
  708. Xlong CrcTable[128];
  709. X
  710. Xvoid
  711. Xcrcinit()
  712. X{    register int i,j;
  713. X    register long sum;
  714. X
  715. X    for (i = 0; i < 128; i++) {
  716. X        sum = 0;
  717. X        for (j = 7-1; j >= 0; --j)
  718. X            if (i & (1 << j))
  719. X                sum ^= POLY >> j;
  720. X        CrcTable[i] = sum;
  721. X    }
  722. X}
  723. X
  724. Xlong
  725. Xfold(s)
  726. X    register char *s;
  727. X{    register long sum = 0;
  728. X    register int c;
  729. X
  730. X    while (c = *s++)
  731. X        sum = (sum >> 7) ^ CrcTable[(sum ^ c) & 0x7f];
  732. X    return sum;
  733. X}
  734. X
  735. Xhashanalyze()
  736. X{    int nodecount = 0, maxlen = 0, len, i, probes = 0;
  737. X    node *n;
  738. X
  739. X    if (!Vflag)
  740. X        return;
  741. X
  742. X    for (i = 0; i < NHASH; i++) {
  743. X        len = 0;
  744. X        for (n = Htable[i]; n; n = n->bucket) {
  745. X            len++;
  746. X            probes += len;
  747. X        }
  748. X        nodecount += len;
  749. X        if (len > maxlen)
  750. X            maxlen = len;
  751. X    }
  752. X    fprintf(stderr,
  753. X      "load = %2.2f, probes/access = %2.2f, %d nodes, max chain is %d\n",
  754. X      (double) nodecount / (double) NHASH,
  755. X      (double) probes / (double) nodecount, nodecount, maxlen);
  756. X}
  757. END_OF_FILE
  758.   if test 13330 -ne `wc -c <'arpatxt.c'`; then
  759.     echo shar: \"'arpatxt.c'\" unpacked with wrong size!
  760.   fi
  761.   # end of 'arpatxt.c'
  762. fi
  763. if test -f 'mapit.c' -a "${1}" != "-c" ; then 
  764.   echo shar: Will not clobber existing file \"'mapit.c'\"
  765. else
  766.   echo shar: Extracting \"'mapit.c'\" \(15685 characters\)
  767.   sed "s/^X//" >'mapit.c' <<'END_OF_FILE'
  768. X/* pathalias -- by steve bellovin, as told to peter honeyman */
  769. X#ifndef lint
  770. Xstatic char    *sccsid = "@(#)mapit.c    9.13 88/06/12";
  771. X#endif
  772. X
  773. X#include "def.h"
  774. X
  775. X#define chkheap(i)    /* void */
  776. X#define chkgap()    /* int */
  777. X
  778. X#define trprint(stream, n) \
  779. X    fprintf((stream), (n)->n_flag & NTERMINAL ? "<%s>" : "%s", (n)->n_name)
  780. X
  781. X/* exports */
  782. X/* invariant while mapping: Nheap < Hashpart */
  783. Xlong Hashpart;        /* start of unreached nodes */
  784. Xlong Nheap;        /* end of heap */
  785. Xlong NumNcopy, Nlink, NumLcopy;
  786. X
  787. Xvoid mapit();
  788. X
  789. X/* imports */
  790. Xextern long Nheap, Hashpart, Tabsize, Tcount;
  791. Xextern int Tflag, Vflag;
  792. Xextern node **Table, *Home;
  793. Xextern char *Linkout, *Graphout;
  794. X
  795. Xextern void freelink(), resetnodes(), printit(), dumpgraph();
  796. Xextern void showlinks(), die();
  797. Xextern long pack(), allocation();
  798. Xextern link *newlink(), *addlink();
  799. Xextern int maptrace(), tiebreaker();
  800. Xextern node *ncopy();
  801. X
  802. X
  803. X/* privates */
  804. Xstatic long    Heaphighwater;
  805. Xstatic link    **Heap;
  806. X
  807. XSTATIC void insert(), heapup(), heapdown(), heapswap(), backlinks();
  808. XSTATIC void setheapbits(), mtracereport(), heapchildren(), otracereport();
  809. XSTATIC link *min_node();
  810. XSTATIC int dehash(), skiplink(), skipterminalalias();
  811. XSTATIC Cost costof();
  812. XSTATIC node *mappedcopy();
  813. X
  814. X/* transform the graph to a shortest-path tree by marking tree edges */
  815. Xvoid
  816. Xmapit()
  817. X{    register node *n;
  818. X    register link *l;
  819. X
  820. X    vprintf(stderr, "*** mapping\ttcount = %ld\n", Tcount);
  821. X    Tflag = Tflag && Vflag;        /* tracing here only if verbose */
  822. X    /* re-use the hash table space for the heap */
  823. X    Heap = (link **) Table;
  824. X    Hashpart = pack(0L, Tabsize - 1);
  825. X
  826. X    /* expunge penalties from -a option and make circular copy lists */
  827. X    resetnodes();
  828. X
  829. X    if (Linkout && *Linkout)    /* dump cheapest links */
  830. X        showlinks();
  831. X    if (Graphout && *Graphout)    /* dump the edge list */
  832. X        dumpgraph();
  833. X
  834. X    /* insert Home to get things started */
  835. X    l = newlink();        /* link to get things started */
  836. X    l->l_to = Home;
  837. X    (void) dehash(Home);
  838. X    insert(l);
  839. X
  840. X    /* main mapping loop */
  841. X    do {
  842. X        Heaphighwater = Nheap;
  843. X        while ((l = min_node()) != 0) {
  844. X            l->l_flag |= LTREE;
  845. X            n = l->l_to;
  846. X            if (n->n_flag & MAPPED)        /* sanity check */
  847. X                die("mapped node in heap");
  848. X            if (Tflag && maptrace(n, n))
  849. X                otracereport(n);    /* tracing */
  850. X            chkheap(1); chkgap();        /* debugging */
  851. X            n->n_flag |= MAPPED;
  852. X            heapchildren(n);    /* add children to heap */
  853. X        }
  854. X        vprintf(stderr, "heap hiwat %d\nalloc %ldk, ncopy = %ld, nlink = %ld, lcopy = %ld\n", Heaphighwater, allocation(), NumNcopy, Nlink, NumLcopy);
  855. X
  856. X        if (Nheap != 0)        /* sanity check */
  857. X            die("null entry in heap");
  858. X
  859. X        /*
  860. X         * add back links from unreachable hosts to reachable
  861. X         * neighbors, then remap.  asymptotically, this is
  862. X         * quadratic; in practice, this is done once or twice,
  863. X         * when n is small.
  864. X         */
  865. X        backlinks();
  866. X    } while (Nheap > 0);
  867. X
  868. X    if (Hashpart < Tabsize) {
  869. X        int foundone = 0;
  870. X
  871. X        for ( ; Hashpart < Tabsize; Hashpart++) {
  872. X            if (Table[Hashpart]->n_flag & ISPRIVATE)
  873. X                continue;
  874. X            if (foundone++ == 0)
  875. X                fputs("You can't get there from here:\n", stderr);
  876. X            putc('\t', stderr);
  877. X            trprint(stderr, Table[Hashpart]);
  878. X            putc('\n', stderr);
  879. X        }
  880. X    }
  881. X}
  882. X
  883. XSTATIC void
  884. Xheapchildren(n)
  885. X    register node *n;
  886. X{    register link *l;
  887. X    register node *next;
  888. X    register int mtrace;
  889. X    register Cost cost;
  890. X
  891. X    for (l = n->n_link; l; l = l->l_next) {
  892. X
  893. X        next = l->l_to;        /* neighboring node */
  894. X        mtrace = Tflag && maptrace(n, next);
  895. X
  896. X        if (l->l_flag & LTREE)
  897. X            continue;
  898. X
  899. X        if (l->l_flag & LTERMINAL)
  900. X            l->l_to = next = ncopy(n, l);
  901. X
  902. X        if ((n->n_flag & NTERMINAL) && (l->l_flag & LALIAS))
  903. X            if (skipterminalalias(n, next))
  904. X                continue;
  905. X            else
  906. X                l->l_to = next = ncopy(n, l);
  907. X
  908. X        if (next->n_flag & MAPPED) {
  909. X            if (mtrace)
  910. X                mtracereport(n, l, "-\talready mapped");
  911. X            continue;
  912. X        }
  913. X        cost = costof(n, l);
  914. X
  915. X        if (skiplink(l, n, cost, mtrace))
  916. X            continue;
  917. X
  918. X        /*
  919. X         * put this link in the heap and restore the
  920. X         * heap property.
  921. X         */
  922. X        if (mtrace) {
  923. X            if (next->n_parent)
  924. X                mtracereport(next->n_parent, l, "*\tdrop");
  925. X            mtracereport(n, l, "+\tadd");
  926. X        }
  927. X        next->n_parent = n;
  928. X        if (dehash(next) == 0) {  /* first time */
  929. X            next->n_cost = cost;
  930. X            insert(l);      /* insert at end */
  931. X            heapup(l);
  932. X        } else {
  933. X            /* replace inferior path */
  934. X            Heap[next->n_tloc] = l;
  935. X            if (cost > next->n_cost) {
  936. X                /* increase cost (gateway) */
  937. X                next->n_cost = cost;
  938. X                heapdown(l);
  939. X            } else if (cost < next->n_cost) {
  940. X                /* cheaper route */
  941. X                next->n_cost = cost;
  942. X
  943. X                heapup(l);
  944. X            }
  945. X        }
  946. X        setheapbits(l);
  947. X        chkheap(1);
  948. X
  949. X    }
  950. X}
  951. X
  952. X/* 
  953. X * bizarro special case.  this merits comment.
  954. X * 
  955. X * n is a terminal node just sucked out of the heap, next is an alias
  956. X * for n.  because n is terminal, it must have one or more "copies."
  957. X * if next is one of those copies, don't put next in the heap.
  958. X *
  959. X * does that clear things up?
  960. X */
  961. XSTATIC int
  962. Xskipterminalalias(n, next)
  963. X    node *n, *next;
  964. X{
  965. X
  966. X    while (n->n_flag & NALIAS) {
  967. X        n = n->n_parent;
  968. X        if (ALTEREGO(n, next))
  969. X            return 1;
  970. X    }
  971. X    return 0;
  972. X}
  973. X
  974. X/*
  975. X * return 1 if we definitely don't want want this link in the
  976. X * shortest path tree, 0 if we might want it, i.e., best so far.
  977. X *
  978. X * if tracing is turned on, report only if this node is being skipped.
  979. X */
  980. XSTATIC int
  981. Xskiplink(l, parent, cost, trace)
  982. X    link *l;        /* new link to this node */
  983. X    node *parent;        /* (potential) new parent of this node */
  984. X    register Cost cost;    /* new cost to this node */
  985. X    int trace;        /* trace this link? */
  986. X{    register node *n;    /* this node */
  987. X    register link *lheap;        /* old link to this node */
  988. X
  989. X    n = l->l_to;
  990. X
  991. X    /* first time we've reached this node? */
  992. X    if (n->n_tloc >= Hashpart)
  993. X        return 0;
  994. X
  995. X    lheap = Heap[n->n_tloc];
  996. X
  997. X    /* examine links to nets that require gateways */
  998. X    if (GATEWAYED(n)) {
  999. X        /* if exactly one is a gateway, use it */
  1000. X        if ((lheap->l_flag & LGATEWAY) && !(l->l_flag & LGATEWAY)) {
  1001. X            if (trace)
  1002. X                mtracereport(parent, l, "-\told gateway");
  1003. X            return 1;    /* old is gateway */
  1004. X        }
  1005. X        if (!(lheap->l_flag & LGATEWAY) && (l->l_flag & LGATEWAY))
  1006. X            return 0;    /* new is gateway */
  1007. X
  1008. X        /* no gateway or both gateways;  resolve in standard way ... */
  1009. X    }
  1010. X
  1011. X    /* examine dup link (sanity check) */
  1012. X    if (n->n_parent == parent && (DEADLINK(lheap) || DEADLINK(l)))
  1013. X        die("dup dead link");
  1014. X
  1015. X    /*  examine cost */
  1016. X    if (cost < n->n_cost)
  1017. X        return 0;
  1018. X    if (cost > n->n_cost) {
  1019. X        if (trace)
  1020. X            mtracereport(parent, l, "-\tcheaper");
  1021. X        return 1;
  1022. X    }
  1023. X
  1024. X    /* all other things being equal, ask the oracle */
  1025. X    if (tiebreaker(n, parent)) {
  1026. X        if (trace)
  1027. X            mtracereport(parent, l, "-\ttiebreaker");
  1028. X        return 1;
  1029. X    }
  1030. X    return 0;
  1031. X}
  1032. X
  1033. X/* compute cost to l->l_to via parent */
  1034. XSTATIC Cost
  1035. Xcostof(prev, l)
  1036. X    register node *prev;
  1037. X    register link *l;
  1038. X{    register node *next;
  1039. X    register Cost cost;
  1040. X
  1041. X    if (l->l_flag & LALIAS)
  1042. X        return prev->n_cost;    /* by definition */
  1043. X
  1044. X    next = l->l_to;
  1045. X    cost = prev->n_cost + l->l_cost;    /* basic cost */
  1046. X
  1047. X    /*
  1048. X     * heuristics:
  1049. X     *    charge for a dead link.
  1050. X     *    charge for getting past a terminal host
  1051. X     *        or getting out of a dead host.
  1052. X     *    charge for getting into a gatewayed net (except at a gateway).
  1053. X     *    discourage mixing of syntax (when prev is a host).
  1054. X     *
  1055. X     * life was simpler when pathalias computed true shortest paths.
  1056. X     */
  1057. X    if (DEADLINK(l))
  1058. X        cost += INF;                /* dead link */
  1059. X    if (DEADHOST(prev))
  1060. X        cost += INF;                /* dead parent */
  1061. X    if (GATEWAYED(next) && !(l->l_flag & LGATEWAY))
  1062. X        cost += INF;                /* not gateway */
  1063. X    if (!ISANET(prev)) {
  1064. X        if ((NETDIR(l) == LLEFT && (prev->n_flag & HASRIGHT))
  1065. X         || (NETDIR(l) == LRIGHT && (prev->n_flag & HASLEFT)))
  1066. X            cost += INF;            /* mixed syntax */
  1067. X    }
  1068. X
  1069. X    return cost;
  1070. X}
  1071. X
  1072. X/* binary heap implementation of priority queue */
  1073. X
  1074. XSTATIC void
  1075. Xinsert(l)
  1076. X    link *l;
  1077. X{    register node *n;
  1078. X
  1079. X    n = l->l_to;
  1080. X    if (n->n_flag & MAPPED)
  1081. X        die("insert mapped node");
  1082. X
  1083. X    Heap[n->n_tloc] = 0;
  1084. X    if (Heap[Nheap+1] != 0)
  1085. X        die("heap error in insert");
  1086. X    if (Nheap++ == 0) {
  1087. X        Heap[1] = l;
  1088. X        n->n_tloc = 1;
  1089. X        return;
  1090. X    }
  1091. X    if (Vflag && Nheap > Heaphighwater)
  1092. X        Heaphighwater = Nheap;    /* diagnostics */
  1093. X
  1094. X    /* insert at the end.  caller must heapup(l). */
  1095. X    Heap[Nheap] = l;
  1096. X    n->n_tloc = Nheap;
  1097. X}
  1098. X
  1099. X/*
  1100. X * "percolate" up the heap by exchanging with the parent.  as in
  1101. X * min_node(), give tiebreaker() a chance to produce better, stable
  1102. X * routes by moving nets and domains close to the root, nets closer
  1103. X * than domains.
  1104. X *
  1105. X * i know this seems obscure, but it's harmless and cheap.  trust me.
  1106. X */
  1107. XSTATIC void
  1108. Xheapup(l)
  1109. X    link *l;
  1110. X{    register long cindx, pindx;    /* child, parent indices */
  1111. X    register Cost cost;
  1112. X    register node *child, *parent;
  1113. X
  1114. X    child = l->l_to;
  1115. X
  1116. X    cost = child->n_cost;
  1117. X    for (cindx = child->n_tloc; cindx > 1; cindx = pindx) {
  1118. X        pindx = cindx / 2;
  1119. X        if (Heap[pindx] == 0)    /* sanity check */
  1120. X            die("impossible error in heapup");
  1121. X        parent = Heap[pindx]->l_to;
  1122. X        if (cost > parent->n_cost)
  1123. X            return;
  1124. X
  1125. X        /* net/domain heuristic */
  1126. X        if (cost == parent->n_cost) {
  1127. X            if (!ISANET(child))
  1128. X                return;
  1129. X            if (!ISADOMAIN(parent))
  1130. X                return;
  1131. X            if (ISADOMAIN(child))
  1132. X                return;
  1133. X        }
  1134. X        heapswap(cindx, pindx);
  1135. X    }
  1136. X}
  1137. X
  1138. X/* extract min (== Heap[1]) from heap */
  1139. XSTATIC link    *
  1140. Xmin_node()
  1141. X{    link *rval, *lastlink;
  1142. X    register link **rheap;
  1143. X
  1144. X    if (Nheap == 0)
  1145. X        return 0;
  1146. X
  1147. X    rheap = Heap;        /* in register -- heavily used */
  1148. X    rval = rheap[1];    /* return this one */
  1149. X
  1150. X    /* move last entry into root and reheap */
  1151. X    lastlink = rheap[Nheap];
  1152. X    rheap[Nheap] = 0;
  1153. X
  1154. X    if (--Nheap) {
  1155. X        rheap[1] = lastlink;
  1156. X        lastlink->l_to->n_tloc = 1;
  1157. X        heapdown(lastlink);    /* restore heap property */
  1158. X    }
  1159. X
  1160. X    return rval;
  1161. X}
  1162. X
  1163. X/*
  1164. X * swap Heap[i] with smaller child, iteratively down the tree.
  1165. X *
  1166. X * given the opportunity, attempt to place nets and domains
  1167. X * near the root.  this helps tiebreaker() shun domain routes.
  1168. X */
  1169. X
  1170. XSTATIC void
  1171. Xheapdown(l)
  1172. X    link *l;
  1173. X{    register long pindx, cindx;
  1174. X    register link **rheap = Heap;    /* in register -- heavily used */
  1175. X    node *child, *rchild, *parent;
  1176. X
  1177. X    pindx = l->l_to->n_tloc;
  1178. X    parent = rheap[pindx]->l_to;    /* invariant */
  1179. X    for ( ; (cindx = pindx * 2) <= Nheap; pindx = cindx) {
  1180. X        /* pick lhs or rhs child */
  1181. X        child = rheap[cindx]->l_to;
  1182. X        if (cindx < Nheap) {
  1183. X            /* compare with rhs child */
  1184. X            rchild = rheap[cindx+1]->l_to;
  1185. X            /*
  1186. X             * use rhs child if smaller than lhs child.
  1187. X             * if equal, use rhs if net or domain.
  1188. X             */
  1189. X            if (child->n_cost > rchild->n_cost) {
  1190. X                child = rchild;
  1191. X                cindx++;
  1192. X            } else if (child->n_cost == rchild->n_cost)
  1193. X                if (ISANET(rchild)) {
  1194. X                    child = rchild;
  1195. X                    cindx++;
  1196. X                }
  1197. X        }
  1198. X
  1199. X        /* child is the candidate for swapping */
  1200. X        if (parent->n_cost < child->n_cost)
  1201. X            break;
  1202. X
  1203. X        /*
  1204. X         * heuristics:
  1205. X         *    move nets/domains up
  1206. X         *    move nets above domains
  1207. X         */
  1208. X        if (parent->n_cost == child->n_cost) {
  1209. X            if (!ISANET(child))
  1210. X                break;
  1211. X            if (ISANET(parent) && ISADOMAIN(child))
  1212. X                break;
  1213. X        }
  1214. X
  1215. X        heapswap(pindx, cindx);
  1216. X    }
  1217. X}
  1218. X
  1219. X/* exchange Heap[i] and Heap[j] pointers */
  1220. XSTATIC void
  1221. Xheapswap(i, j)
  1222. X    long i, j;
  1223. X{    register link *temp, **rheap;
  1224. X
  1225. X    rheap = Heap;    /* heavily used -- put in register */
  1226. X    temp = rheap[i];
  1227. X    rheap[i] = rheap[j];
  1228. X    rheap[j] = temp;
  1229. X    rheap[j]->l_to->n_tloc = j;
  1230. X    rheap[i]->l_to->n_tloc = i;
  1231. X}
  1232. X
  1233. X/* return 1 if n is already de-hashed (n_tloc < Hashpart), 0 o.w. */
  1234. XSTATIC int
  1235. Xdehash(n)
  1236. X    register node *n;
  1237. X{
  1238. X    if (n->n_tloc < Hashpart)
  1239. X        return 1;
  1240. X
  1241. X    /* swap with entry in Table[Hashpart] */
  1242. X    Table[Hashpart]->n_tloc = n->n_tloc;
  1243. X    Table[n->n_tloc] = Table[Hashpart];
  1244. X    Table[Hashpart] = n;
  1245. X
  1246. X    n->n_tloc = Hashpart++;
  1247. X    return 0;
  1248. X}
  1249. X
  1250. X/*
  1251. X * everything reachable has been mapped.  what to do about any
  1252. X * unreachable hosts?  the sensible thing to do is to dump them on
  1253. X * stderr and be done with it.  unfortunately, there are hundreds of
  1254. X * such hosts in the usenet maps.  so we take the low road: for each
  1255. X * unreachable host, we add a back link from its cheapest mapped child,
  1256. X * in the faint that a reverse path works.
  1257. X *
  1258. X * beats me why people want their error output in their map databases.
  1259. X */
  1260. XSTATIC void
  1261. Xbacklinks()
  1262. X{    register link *l;
  1263. X    register node *n, *child;
  1264. X    node *nomap;
  1265. X    long i;
  1266. X
  1267. X    /* hosts from Hashpart to Tabsize are unreachable */
  1268. X    for (i = Hashpart; i < Tabsize; i++) {
  1269. X        nomap = Table[i];
  1270. X        /* if a copy has been mapped, we're ok */
  1271. X        if (nomap->n_copy != nomap) {
  1272. X            dehash(nomap);
  1273. X            Table[nomap->n_tloc] = 0;
  1274. X            nomap->n_tloc = 0;
  1275. X            continue;
  1276. X        }
  1277. X
  1278. X        /* TODO: simplify this */        
  1279. X        /* add back link from minimal cost child */
  1280. X        child = 0;
  1281. X        for (l = nomap->n_link; l; l = l->l_next) {
  1282. X            n = l->l_to;
  1283. X            /* never ever ever crawl out of a domain */
  1284. X            if (ISADOMAIN(n))
  1285. X                continue;
  1286. X            if ((n = mappedcopy(n)) == 0)
  1287. X                continue;
  1288. X            if (child == 0) {
  1289. X                child = n;
  1290. X                continue;
  1291. X            }
  1292. X            if (n->n_cost > child->n_cost)
  1293. X                continue;
  1294. X            if (n->n_cost == child->n_cost) {
  1295. X                nomap->n_parent = child; /* for tiebreaker */
  1296. X                if (tiebreaker(nomap, n))
  1297. X                    continue;
  1298. X            }
  1299. X            child = n;
  1300. X        }
  1301. X        if (child == 0)
  1302. X            continue;
  1303. X        (void) dehash(nomap);
  1304. X        l = addlink(child, nomap, INF, DEFNET, DEFDIR);    /* INF cost */
  1305. X        nomap->n_parent = child;
  1306. X        nomap->n_cost = costof(child, l);
  1307. X        insert(l);
  1308. X        heapup(l);
  1309. X        if (Vflag > 1)
  1310. X            fprintf(stderr, "backlink: %s <- %s\n", nomap->n_name, child->n_name);
  1311. X    }
  1312. X    vprintf(stderr, "%d backlinks\n", Nheap);
  1313. X}
  1314. X
  1315. X/* find a mapped copy of n if it exists */
  1316. XSTATIC node *
  1317. Xmappedcopy(n)
  1318. X    register node *n;
  1319. X{    register node *ncp;
  1320. X
  1321. X    if (n->n_flag & MAPPED)
  1322. X        return n;
  1323. X    for (ncp = n->n_copy; ncp != n; ncp = ncp->n_copy)
  1324. X        if (ncp->n_flag & MAPPED)
  1325. X            return ncp;
  1326. X    return 0;
  1327. X}
  1328. X
  1329. X/*
  1330. X * l has just been added or changed in the heap,
  1331. X * so reset the state bits for l->l_to.
  1332. X */
  1333. XSTATIC void
  1334. Xsetheapbits(l)
  1335. X    register link *l;
  1336. X{    register node *n;
  1337. X    register node *parent;
  1338. X
  1339. X    n = l->l_to;
  1340. X    parent = n->n_parent;
  1341. X    n->n_flag &= ~(NALIAS|HASLEFT|HASRIGHT);    /* reset */
  1342. X
  1343. X    /* record whether link is an alias */
  1344. X    if (l->l_flag & LALIAS) {
  1345. X        n->n_flag |= NALIAS;
  1346. X        /* TERMINALity is inherited by the alias */
  1347. X        if (parent->n_flag & NTERMINAL)
  1348. X            n->n_flag |= NTERMINAL;
  1349. X    }
  1350. X
  1351. X    /* set left/right bits */
  1352. X    if (NETDIR(l) == LLEFT || (parent->n_flag & HASLEFT))
  1353. X        n->n_flag |= HASLEFT;
  1354. X    if (NETDIR(l) == LRIGHT || (parent->n_flag & HASRIGHT))
  1355. X        n->n_flag |= HASRIGHT;
  1356. X}
  1357. X
  1358. XSTATIC void
  1359. Xmtracereport(from, l, excuse)
  1360. X    node *from;
  1361. X    link *l;
  1362. X    char *excuse;
  1363. X{    node *to = l->l_to;
  1364. X
  1365. X    fprintf(stderr, "%-16s ", excuse);
  1366. X    trprint(stderr, from);
  1367. X    fputs(" -> ", stderr);
  1368. X    trprint(stderr, to);
  1369. X    fprintf(stderr, " (%ld, %ld, %ld) ", from->n_cost, l->l_cost, to->n_cost);
  1370. X    if (to->n_parent) {
  1371. X        trprint(stderr, to->n_parent);
  1372. X        fprintf(stderr, " (%ld)", to->n_parent->n_cost);
  1373. X    }
  1374. X    putc('\n', stderr);
  1375. X}
  1376. X
  1377. XSTATIC void
  1378. Xotracereport(n)
  1379. X    node *n;
  1380. X{
  1381. X    if (n->n_parent)
  1382. X        trprint(stderr, n->n_parent);
  1383. X    else
  1384. X        fputs("[root]", stderr);
  1385. X    fputs(" -> ", stderr);
  1386. X    trprint(stderr, n);
  1387. X    fputs(" mapped\n", stderr);
  1388. X}
  1389. X    
  1390. X#if 0
  1391. X/* extremely time consuming, exhaustive check of heap sanity. */
  1392. Xchkheap(i)
  1393. X{    int lhs, rhs;
  1394. X
  1395. X    lhs = i * 2;
  1396. X    rhs = lhs + 1;
  1397. X
  1398. X    if (lhs <= Nheap) {
  1399. X        if (Heap[i]->l_to->n_cost > Heap[lhs]->l_to->n_cost)
  1400. X            die("chkheap failure on lhs");
  1401. X        chkheap(lhs);
  1402. X    }
  1403. X    if (rhs <= Nheap) {
  1404. X        if (Heap[i]->l_to->n_cost > Heap[rhs]->l_to->n_cost)
  1405. X            die("chkheap failure on rhs");
  1406. X        chkheap(rhs);
  1407. X    }
  1408. X#if 00
  1409. X    /* this hasn't been used for years */
  1410. X    for (i = 1; i < Nheap; i++) {
  1411. X        link *l;
  1412. X
  1413. X        vprintf(stderr, "%5d %-16s", i, Heap[i]->l_to->n_name);
  1414. X        if ((l = Heap[i]->l_to->n_link) != 0) do {
  1415. X            vprintf(stderr, "%-16s", l->l_to->n_name);
  1416. X        } while ((l = l->l_next) != 0);
  1417. X        vprintf(stderr, "\n");
  1418. X    }
  1419. X    for (i = Hashpart; i < Tabsize; i++) {
  1420. X        link *l;
  1421. X        node *n;
  1422. X
  1423. X        vprintf(stderr, "%5d %-16s", i, Table[i]->n_name);
  1424. X        if ((l = Table[i]->n_link) != 0) do {
  1425. X            vprintf(stderr, "%-16s", l->l_to->n_name);
  1426. X        } while ((l = l->l_next) != 0);
  1427. X        vprintf(stderr, "\n");
  1428. X    }
  1429. X#endif /*00*/
  1430. X        
  1431. X}
  1432. X#endif /*0*/
  1433. X
  1434. X/* this isn't much use */
  1435. X#if 0
  1436. XSTATIC int
  1437. Xchkgap()
  1438. X{    static int gap = -1;
  1439. X    int newgap;
  1440. X
  1441. X    newgap = Hashpart - Nheap;
  1442. X    if (gap == -1 || newgap < gap)
  1443. X        gap = newgap;
  1444. X    return gap;
  1445. X}
  1446. X#endif /*0*/
  1447. END_OF_FILE
  1448.   if test 15685 -ne `wc -c <'mapit.c'`; then
  1449.     echo shar: \"'mapit.c'\" unpacked with wrong size!
  1450.   fi
  1451.   # end of 'mapit.c'
  1452. fi
  1453. if test -f 'mem.c' -a "${1}" != "-c" ; then 
  1454.   echo shar: Will not clobber existing file \"'mem.c'\"
  1455. else
  1456.   echo shar: Extracting \"'mem.c'\" \(4416 characters\)
  1457.   sed "s/^X//" >'mem.c' <<'END_OF_FILE'
  1458. X/* pathalias -- by steve bellovin, as told to peter honeyman */
  1459. X#ifndef lint
  1460. Xstatic char    *sccsid = "@(#)mem.c    9.2 88/06/10";
  1461. X#endif
  1462. X
  1463. X#include "def.h"
  1464. X
  1465. X/* exports */
  1466. Xlong Ncount;
  1467. Xextern void freelink(), wasted(), freetable();
  1468. Xextern long allocation();
  1469. X
  1470. X/* imports */
  1471. Xextern char *Netchars;
  1472. Xextern int Vflag;
  1473. Xextern char *sbrk();
  1474. Xextern void die();
  1475. Xextern int strlen();
  1476. X
  1477. X/* privates */
  1478. XSTATIC void nomem();
  1479. Xstatic link *Lcache;
  1480. Xstatic unsigned int Memwaste;
  1481. X
  1482. Xlink    *
  1483. Xnewlink()
  1484. X{    register link *rval;
  1485. X
  1486. X    if (Lcache) {
  1487. X         rval = Lcache;
  1488. X        Lcache = Lcache->l_next;
  1489. X        strclear((char *) rval, sizeof(link));
  1490. X    } else if ((rval = (link * ) calloc(1, sizeof(link))) == 0)
  1491. X        nomem();
  1492. X    return rval;
  1493. X}
  1494. X
  1495. X/* caution: this destroys the contents of l_next */
  1496. Xvoid
  1497. Xfreelink(l)
  1498. X    link *l;
  1499. X{
  1500. X    l->l_next = Lcache;
  1501. X    Lcache = l;
  1502. X}
  1503. X
  1504. Xnode    *
  1505. Xnewnode()
  1506. X{    register node *rval;
  1507. X
  1508. X    if ((rval = (node * ) calloc(1, sizeof(node))) == 0)
  1509. X        nomem();
  1510. X    Ncount++;
  1511. X    return rval;
  1512. X}
  1513. X
  1514. Xchar    *
  1515. Xstrsave(s)
  1516. X    char *s;
  1517. X{    register char *r;
  1518. X
  1519. X    if ((r = malloc((unsigned) strlen(s) + 1)) == 0)
  1520. X        nomem();
  1521. X    (void) strcpy(r, s);
  1522. X    return r;
  1523. X}
  1524. X
  1525. X#ifndef strclear
  1526. Xvoid
  1527. Xstrclear(str, len)
  1528. X    register char *str;
  1529. X    register long len;
  1530. X{
  1531. X    while (--len >= 0)
  1532. X        *str++ = 0;
  1533. X}
  1534. X#endif /*strclear*/
  1535. X
  1536. Xnode    **
  1537. Xnewtable(size)
  1538. X    long size;
  1539. X{    register node **rval;
  1540. X
  1541. X    if ((rval = (node **) calloc(1, (unsigned int) size * sizeof(node *))) == 0) 
  1542. X        nomem();
  1543. X    return rval;
  1544. X}
  1545. X
  1546. Xvoid
  1547. Xfreetable(t, size)
  1548. X    node **t;
  1549. X    long size;
  1550. X{
  1551. X#ifdef MYMALLOC
  1552. X    extern void addtoheap();
  1553. X
  1554. X    addtoheap((char *) t, size * sizeof(node *));
  1555. X#else
  1556. X    free((char *) t);
  1557. X#endif
  1558. X}
  1559. X
  1560. XSTATIC void
  1561. Xnomem()
  1562. X{
  1563. X    static char epitaph[128];
  1564. X
  1565. X    sprintf(epitaph, "out of memory (%ldk allocated)", allocation());
  1566. X    die(epitaph);
  1567. X}
  1568. X
  1569. X/* data space allocation -- main sets `dataspace' very early */
  1570. Xlong
  1571. Xallocation()
  1572. X{
  1573. X    static char *dataspace;
  1574. X    long rval;
  1575. X
  1576. X    if (dataspace == 0) {        /* first time */
  1577. X        dataspace = sbrk(0);    /* &end? */
  1578. X        return 0;
  1579. X    }
  1580. X    rval = (sbrk(0) - dataspace)/1024;
  1581. X    if (rval < 0)            /* funny architecture? */
  1582. X        rval = -rval;
  1583. X    return rval;
  1584. X}
  1585. X
  1586. X/* how much memory has been wasted? */
  1587. Xvoid
  1588. Xwasted()
  1589. X{
  1590. X    if (Memwaste == 0)
  1591. X        return;
  1592. X    vprintf(stderr, "memory allocator wasted %ld bytes\n", Memwaste);
  1593. X}
  1594. X
  1595. X#ifdef MYMALLOC
  1596. X
  1597. X/* use c library malloc/calloc here, and here only */
  1598. X#undef malloc
  1599. X#undef calloc
  1600. X
  1601. X/* imports */
  1602. Xextern char *malloc(), *calloc();
  1603. X
  1604. X/* private */
  1605. XSTATIC int align();
  1606. X
  1607. X/* allocate in MBUFSIZ chunks.  4k works ok (less 16 for malloc quirks). */
  1608. X#define MBUFSIZ (4 * 1024 - 16)
  1609. X
  1610. X/* 
  1611. X * mess with ALIGN at your peril.  longword (== 0 mod 4)
  1612. X * alignment seems to work everywhere.
  1613. X */
  1614. X
  1615. X#define ALIGN 2
  1616. X
  1617. Xtypedef struct heap heap;
  1618. Xstruct heap {
  1619. X    heap *h_next;
  1620. X    long h_size;
  1621. X};
  1622. X
  1623. Xstatic heap *Mheap;    /* not to be confused with a priority queue */
  1624. X
  1625. XSTATIC void
  1626. Xaddtoheap(p, size)
  1627. X    char *p;
  1628. X    long size;
  1629. X{    int adjustment;
  1630. X    heap *pheap;
  1631. X
  1632. X    /* p is aligned, but it doesn't hurt to check */
  1633. X    adjustment = align(p);
  1634. X    p += adjustment;
  1635. X    size -= adjustment;
  1636. X
  1637. X    if (size < 1024)
  1638. X        return;        /* can't happen */
  1639. X    pheap = (heap *) p;    /* pheap is shorthand */
  1640. X    pheap->h_next = Mheap;
  1641. X    pheap->h_size = size;
  1642. X    Mheap = pheap;
  1643. X}
  1644. X
  1645. X/*
  1646. X * buffered malloc()
  1647. X *    returns space initialized to 0.  calloc isn't used, since
  1648. X *    strclear can be faster.
  1649. X *
  1650. X * free is ignored, except for very large objects,
  1651. X * which are returned to the heap with addtoheap(). 
  1652. X */
  1653. X
  1654. Xchar    *
  1655. Xmymalloc(n)
  1656. X    register unsigned int n;
  1657. X{    static unsigned int size; /* how much do we have on hand? */
  1658. X    static char *mstash;      /* where is it? */
  1659. X    register char *rval;
  1660. X
  1661. X    if (n >= 1024) {        /* for hash table */
  1662. X        rval = malloc(n);    /* aligned */
  1663. X        if (rval)
  1664. X            strclear(rval, n);
  1665. X        return rval;
  1666. X    }
  1667. X
  1668. X    n += align((char *) n);    /* keep everything aligned */
  1669. X
  1670. X    if (n > size) {
  1671. X        Memwaste += size;    /* toss the fragment */
  1672. X        /* look in the heap */
  1673. X        if (Mheap) {
  1674. X            mstash = (char *) Mheap;    /* aligned */
  1675. X            size = Mheap->h_size;
  1676. X            Mheap = Mheap->h_next;
  1677. X        } else {
  1678. X            mstash = malloc(MBUFSIZ);    /* aligned */
  1679. X            if (mstash == 0) {
  1680. X                size = 0;
  1681. X                return 0;
  1682. X            }
  1683. X            size = MBUFSIZ;
  1684. X        }
  1685. X        strclear(mstash, size);        /* what if size > 2^16? */
  1686. X    }
  1687. X    rval = mstash;
  1688. X    mstash += n;
  1689. X    size -= n;
  1690. X    return rval;
  1691. X}
  1692. X
  1693. X/*
  1694. X * what's the (mis-)alignment of n?  return the complement of
  1695. X * n mod 2^ALIGN
  1696. X */
  1697. XSTATIC int
  1698. Xalign(n)
  1699. X    char *n;
  1700. X{    register int abits;    /* misalignment bits in n */
  1701. X
  1702. X    abits = (int) n & ~(0xff << ALIGN) & 0xff;
  1703. X    if (abits == 0)
  1704. X        return 0;
  1705. X    return (1 << ALIGN) - abits;
  1706. X}
  1707. X
  1708. X#endif /*MYMALLOC*/
  1709. END_OF_FILE
  1710.   if test 4416 -ne `wc -c <'mem.c'`; then
  1711.     echo shar: \"'mem.c'\" unpacked with wrong size!
  1712.   fi
  1713.   # end of 'mem.c'
  1714. fi
  1715. if test -f 'pathalias.8' -a "${1}" != "-c" ; then 
  1716.   echo shar: Will not clobber existing file \"'pathalias.8'\"
  1717. else
  1718.   echo shar: Extracting \"'pathalias.8'\" \(12597 characters\)
  1719.   sed "s/^X//" >'pathalias.8' <<'END_OF_FILE'
  1720. X.\" @(#)pathalias.8    9.5 88/05/10
  1721. X.TH PATHALIAS 8 "5/10/88" "Public Domain"
  1722. X.SH NAME
  1723. Xpathalias, makedb, arpatxt \- mail routing tools
  1724. X.SH SYNOPSIS
  1725. X.B pathalias
  1726. X[
  1727. X.B \-ivcDf
  1728. X] [
  1729. X.BI \-t \0link
  1730. X] [
  1731. X.BI \-l \0host
  1732. X] [
  1733. X.BI \-d \0link
  1734. X] [
  1735. X.ig
  1736. X.\" for pathparse.
  1737. X.BI \-g \0file
  1738. X] [
  1739. X..
  1740. X.I files ...
  1741. X]
  1742. X.PP
  1743. X.B makedb
  1744. X[
  1745. X.B \-a
  1746. X] [
  1747. X.BI \-o \0dbmfile
  1748. X] [
  1749. X.I files ...
  1750. X]
  1751. X.PP
  1752. X.B arpatxt
  1753. X[
  1754. X.B \-@fi
  1755. X] [
  1756. X.BI \-g \0gateway
  1757. X] [
  1758. X.BI \-p \0privatefile
  1759. X] [
  1760. X.BI \-d \0directory
  1761. X] [
  1762. X.I files ...
  1763. X]
  1764. X.ad b
  1765. X.SH DESCRIPTION
  1766. X.I Pathalias
  1767. Xcomputes the shortest paths and corresponding routes from one host
  1768. X(computer system) to all other known, reachable hosts.
  1769. X.I Pathalias
  1770. Xreads host-to-host connectivity
  1771. Xinformation on standard input or in the named
  1772. X.IR files ,
  1773. Xand writes a list of
  1774. Xhost-route pairs on the standard output.
  1775. X.PP
  1776. XHere are the
  1777. X.I pathalias
  1778. Xoptions:
  1779. X.TP 6
  1780. X.B \-i
  1781. XIgnore case:  map all host names to lower case.
  1782. XBy default, case is significant.
  1783. X.TP
  1784. X.B \-c
  1785. XPrint costs: print the path cost before each host-route pair.
  1786. X.TP
  1787. X.B \-v
  1788. XVerbose: report some statistics on the standard error output.
  1789. X.TP
  1790. X.B \-D
  1791. XTerminal domains: see 
  1792. X.I domains 
  1793. Xsection.
  1794. X.TP
  1795. X.B \-f
  1796. XFirst hop cost: the printed cost is the cost to the first relay in a path,
  1797. Xinstead of the cost of the path itself; implies (and overrides) the
  1798. X.B \-c
  1799. Xoption.
  1800. X.ig
  1801. X.\" the -g option is for pathparse and is not for public consumption (yet!).
  1802. X.TP
  1803. X.BI \-g \0file
  1804. XDump the edges of the graph into the named file.
  1805. X..
  1806. X.TP
  1807. X.BI \-l \0host
  1808. XSet local host name to
  1809. X.IR host .
  1810. XBy default,
  1811. X.I pathalias
  1812. Xdiscovers the local host name in a system-dependent way.
  1813. X.TP
  1814. X.BI \-d \0arg
  1815. XDeclare a dead link, host, or network.
  1816. XIf
  1817. X.I arg
  1818. Xis of the form ``host-1!host-2,'' the link from host-1 to host-2
  1819. Xis treated as an extremely high cost (\fIi.e.\fP, \s-1DEAD\s0) link.
  1820. XIf
  1821. X.I arg
  1822. Xis a single host name,
  1823. Xthat host is treated as dead
  1824. Xand is used as a relay host of last resort on any path.
  1825. XIf
  1826. X.I arg
  1827. Xis a network name, the network requires a gateway.
  1828. X.TP
  1829. X.BI \-t \0arg
  1830. XTrace input for link, host or network on the standard error output.
  1831. XThe form of
  1832. X.I arg
  1833. Xis as above.
  1834. X.PP
  1835. X.I Makedb
  1836. Xtakes
  1837. X.I pathalias
  1838. Xoutput and creates or appends to a
  1839. X.IR dbm (3)
  1840. Xdatabase.
  1841. X.PP
  1842. XHere are the
  1843. X.I makedb
  1844. Xoptions:
  1845. X.TP 6
  1846. X.B \-a
  1847. XAppend to an existing database;
  1848. Xby default,
  1849. X.I makedb
  1850. Xtruncates the database.
  1851. X.TP
  1852. X.BI \-o \0dbmfile
  1853. XIdentify the output file base name.
  1854. X.PP
  1855. X.I Arpatxt
  1856. Xconverts the Internet hosts table
  1857. X.I hosts.txt
  1858. Xinto
  1859. X.I pathalias
  1860. Xinput.
  1861. X.PP
  1862. XHere are the
  1863. X.I arpatxt
  1864. Xoptions:
  1865. X.TP 6
  1866. X.B \-@
  1867. XGenerate
  1868. X.I pathalias
  1869. Xinput that specifies `@' style addressing.  The default
  1870. Xis to produce
  1871. X.I pathalias
  1872. Xinput that specifies `!' style addressing.
  1873. X.TP
  1874. X.B \-f
  1875. X\&``Filter mode'' \(em write output on stdout.  Normally,
  1876. X.I arpatxt
  1877. Xwrites the description of each domain into a separate file.
  1878. X.TP
  1879. X.B \-i
  1880. XMap output to lower case.
  1881. X.TP
  1882. X.BI \-g \0arg
  1883. XDeclare a gateway to the Internet or one of its subdomains.  If
  1884. X.I arg
  1885. Xcontains one or more dots, the left-hand side component that contains
  1886. Xno dots is declared a gateway to the domain to the right of the dot.
  1887. XOtherwise,
  1888. X.I arg
  1889. Xis declared a gateway to the Internet as a whole.
  1890. X.TP
  1891. X.BI \-p \0privatefile
  1892. X.I Privatefile
  1893. Xcontains a list of host names that conflict with other names.
  1894. X.TP
  1895. X.BI \-d \0directory
  1896. XWrite output files in
  1897. X.IR directory .
  1898. X.SS \fIPathalias\fP Input Format
  1899. XA line beginning with white space continues the preceding line.
  1900. XAnything following `#' on an input line is ignored.
  1901. X.PP
  1902. XA list of host-to-host connections consists of a ``from'' host in column 1,
  1903. Xfollowed by white space,
  1904. Xfollowed by a comma-separated list of ``to' hosts, called
  1905. X.IR links .
  1906. XA link may be preceded or followed by a network character to use
  1907. Xin the route.
  1908. XValid network characters are `!' (default), `@', `:', and `%'.
  1909. XA link (and network character, if present) may be
  1910. Xfollowed by a ``cost'' enclosed in parentheses.
  1911. XCosts may be arbitrary
  1912. Xarithmetic expressions involving numbers, parentheses, `+', `\-', `*',
  1913. Xand `/'.
  1914. XNegative costs are prohibited.
  1915. XThe following symbolic costs are
  1916. Xrecognized:
  1917. X.PP
  1918. X.RS
  1919. X.nf
  1920. X.ta 14mR 17m
  1921. X\s-1LOCAL\s0    25    (local-area network connection)
  1922. X\s-1DEDICATED\s0    95    (high speed dedicated link)
  1923. X\s-1DIRECT\s0    200    (toll-free call)
  1924. X\s-1DEMAND\s0    300    (long-distance call)
  1925. X\s-1HOURLY\s0    500    (hourly poll)
  1926. X\s-1EVENING\s0    1800    (time restricted call)
  1927. X\s-1DAILY\s0    5000    (daily poll, also called \s-1POLLED\s0)
  1928. X\s-1WEEKLY\s0    30000    (irregular poll)
  1929. X.fi
  1930. X.RE
  1931. X.PP
  1932. XIn addition,
  1933. X.SM DEAD
  1934. Xis a very large number (effectively infinite),
  1935. X.SM HIGH
  1936. Xand
  1937. X.SM LOW
  1938. Xare \-5 and +5 respectively,
  1939. Xfor baud-rate or quality bonuses/penalties,
  1940. Xand
  1941. X.SM FAST
  1942. Xis \-80, for adjusting costs of links that use high-speed (9.6 Kbaud or more) modems.
  1943. XThese symbolic costs represent an imperfect measure of bandwidth,
  1944. Xmonetary cost, and frequency of connections.
  1945. XFor most mail traffic, it is important to minimize the number
  1946. Xof hosts in a route,
  1947. Xthus,
  1948. X.IR e.g. ,
  1949. X.SM HOURLY
  1950. X\&* 24
  1951. Xis much larger than
  1952. X.SM DAILY.
  1953. XIf no cost is given,
  1954. Xa default of 4000 is used.
  1955. X.PP
  1956. XFor the most part, arithmetic expressions that mix symbolic constants
  1957. Xother than
  1958. X.SM HIGH,
  1959. X.SM LOW,
  1960. Xand
  1961. X.SM FAST
  1962. Xmake no sense.
  1963. X.IR E.g. ,
  1964. Xif a host calls a local neighbor whenever there is work,
  1965. Xand additionally polls every evening,
  1966. Xthe cost is
  1967. X.SM DIRECT,
  1968. X.B not
  1969. X.SM DIRECT+EVENING.
  1970. X.PP
  1971. XSome examples:
  1972. X.PP
  1973. X.RS
  1974. X.nf
  1975. X.ta 10m 15m
  1976. Xdown    princeton!(\s-1DEDICATED\s0), tilt,
  1977. X    %thrash(\s-1LOCAL\s0)
  1978. Xprinceton    topaz!(\s-1DEMAND\s0+\s-1LOW\s0)
  1979. Xtopaz    @rutgers(\s-1LOCAL\s0+1)
  1980. X.fi
  1981. X.RE
  1982. X.PP
  1983. XIf a link is encountered more than once,
  1984. Xthe least-cost occurrence dictates the cost and network character.
  1985. XLinks are treated as bidirectional but asymmetric:
  1986. Xfor each link declared in the input, a
  1987. X.SM DEAD
  1988. Xreverse link is assumed.
  1989. X.PP
  1990. XIf the ``to'' host in a link is surrounded by angle brackets,
  1991. Xthe link is considered
  1992. X.IR terminal ,
  1993. Xand
  1994. Xfurther links beyond this one are heavily penalized.
  1995. X.IR E.g. ,
  1996. Xwith input
  1997. X.PP
  1998. X.RS
  1999. X.nf
  2000. X.ta 10m 15m
  2001. Xseismo    <research>(10), research(100), ihnp4(10)
  2002. Xresearch    allegra(10)
  2003. Xihnp4    allegra(50)
  2004. X.fi
  2005. X.RE
  2006. X.PP
  2007. Xthe path from seismo to research is direct, but the path from seismo
  2008. Xto allegra
  2009. Xuses ihnp4 as a relay, not research.
  2010. X.PP
  2011. XThe set of names by which a host is known to its neighbors is
  2012. Xcalled its
  2013. X.IR aliases .
  2014. XAliases are declared as follows:
  2015. X.PP
  2016. X.RS
  2017. Xname = alias, alias ...
  2018. X.RE
  2019. X.PP
  2020. XThe name used in the route to or through aliased hosts
  2021. Xis the name by which the host is known
  2022. Xto its predecessor in the route.
  2023. X.PP
  2024. XFully connected networks, such as the
  2025. X.SM ARPANET
  2026. Xor a local-area network,
  2027. Xare declared as follows:
  2028. X.PP
  2029. X.RS
  2030. Xnet = {host, host, ...}
  2031. X.RE
  2032. X.PP
  2033. XThe host-list may be preceded or followed by a routing
  2034. Xcharacter (`!' default), and may be followed by a cost (default 4000).
  2035. XThe network name is optional; if not given,
  2036. X.I pathalias
  2037. Xmakes one up.
  2038. X.PP
  2039. X.RS
  2040. X.nf
  2041. Xetherhosts = {rahway, milan, joliet}!(\s-1LOCAL\s0)
  2042. Xringhosts = @{gimli, alida, almo}(\s-1DEDICATED\s0)
  2043. X= {etherhosts, ringhosts}(0)
  2044. X.fi
  2045. X.RE
  2046. X.PP
  2047. XThe routing character used in a route to a network member is the one
  2048. Xencountered when ``entering'' the network.
  2049. XSee also the sections on
  2050. X.I gateways
  2051. Xand
  2052. X.I domains .
  2053. X.PP
  2054. XConnection data may be given while hiding host names
  2055. Xby declaring
  2056. X.PP
  2057. X.RS
  2058. Xprivate {host, host, ...}
  2059. X.RE
  2060. X.PP
  2061. X.I Pathalias
  2062. Xwill not generate routes for private hosts, but may produce routes
  2063. Xthrough them.
  2064. XThe scope of a private declaration extends from the declaration to the end of
  2065. Xthe input file in which it appears, or to a private declaration with an empty
  2066. Xhost list, whichever comes first.
  2067. XThe latter scope rule offers a way to retain the
  2068. Xsemantics of private declarations when
  2069. Xreading from the standard input.
  2070. X.PP
  2071. XDead hosts, links, or networks may be presented in the input stream by declaring
  2072. X.PP
  2073. X.RS
  2074. Xdead {arg, ...}
  2075. X.RE
  2076. X.PP
  2077. Xwhere
  2078. X.I arg
  2079. Xhas the same form as the argument to the
  2080. X.B \-d
  2081. Xoption.
  2082. X.PP
  2083. XTo force a specific cost for a link, delete all prior declarations with
  2084. X.PP
  2085. X.RS
  2086. Xdelete {host-1!host-2}
  2087. X.RE
  2088. X.PP
  2089. Xand declare the link as desired.
  2090. XTo delete a host and all its links, use
  2091. X.PP
  2092. X.RS
  2093. Xdelete {host}
  2094. X.RE
  2095. X.PP
  2096. XError diagnostics refer to the file in which the error was found.
  2097. XTo alter the file name, use
  2098. X.PP
  2099. X.RS
  2100. Xfile {filename}
  2101. X.RE
  2102. X.PP
  2103. XFine-tuning is possible by adjusting the weights
  2104. Xof all links from a given host, as in
  2105. X.PP
  2106. X.RS
  2107. Xadjust {host-1, host-2(LOW), host-3(\-1)}
  2108. X.RE
  2109. X.PP
  2110. XIf no cost is given a default of 4000 is used.
  2111. X.PP
  2112. XInput from compressed (and uncompressed) files can be
  2113. Xpiped into 
  2114. X.I pathalias
  2115. Xwith the following script.
  2116. X.PP
  2117. X.RS
  2118. X.nf
  2119. Xfor i in $*; do
  2120. X    case $i in
  2121. X    *.Z)    echo "file {`expr $i : '\(.*\).Z'`}
  2122. X        zcat $i ;;
  2123. X    *)    echo "file {$i}"
  2124. X        cat $i ;;
  2125. X    esac
  2126. X    echo "private {}"
  2127. Xdone
  2128. X.fi
  2129. X.RE
  2130. X.PP
  2131. X.SS Output Format
  2132. XA list of host-route pairs is written to the standard output,
  2133. Xwhere route is a string appropriate for use with
  2134. X.IR printf (3),
  2135. X.IR e.g. ,
  2136. X.PP
  2137. X.RS
  2138. X.nf
  2139. X.ta 10m 20m
  2140. Xrutgers    princeton!topaz!%s@rutgers
  2141. X.fi
  2142. X.RE
  2143. X.PP
  2144. XThe ``%s'' in the route string should be replaced by the
  2145. Xuser name at the destination host.
  2146. X(This task is normally performed by a mailer.)
  2147. X.PP
  2148. XExcept for
  2149. X.IR domains ,
  2150. Xthe name of a network is never used in
  2151. Xroutes.
  2152. XThus, in the earlier example, the path from down to
  2153. Xup would be ``up!%s,'' not ``princeton-ethernet!up!%s.''
  2154. X.SS Gateways
  2155. XA network is represented by
  2156. Xa pseudo-host and a set of network members.
  2157. XLinks from the members to the network have the weight given in
  2158. Xthe input, while the cost from the network to the members is zero.
  2159. XIf a network is declared dead,
  2160. Xthe member-to-network links are marked dead,
  2161. Xwhich effectively prohibits access to the network
  2162. Xfrom its members.
  2163. X.PP
  2164. XHowever, if the input also shows an explicit link from any host to the network,
  2165. Xthen that host can be used as a gateway.
  2166. X(In particular, the gateway need not be a network member.)
  2167. X.PP
  2168. X.IR E.g. ,
  2169. Xif
  2170. X.SM CSNET
  2171. Xis declared dead
  2172. Xand the input contains
  2173. X.PP
  2174. X.RS
  2175. X.nf
  2176. X.ta 10m 20m
  2177. X\s-1CSNET\s0 = {...}
  2178. Xcsnet-relay    \s-1CSNET\s0
  2179. X.fi
  2180. X.RE
  2181. X.PP
  2182. Xthen routes to
  2183. X.SM CSNET
  2184. Xhosts will use csnet-relay as a gateway.
  2185. X.SS Domains
  2186. XA network whose name begins with `.' is called
  2187. Xa domain.
  2188. XDomains are presumed to require gateways,
  2189. X.IR i.e. ,
  2190. Xthey are \s-1DEAD\s0.
  2191. XThe route given by a path through a domain is similar to
  2192. Xthat for a network, but here
  2193. Xthe domain name is tacked onto the end of the next host.
  2194. XSubdomains are permitted.
  2195. X.PP
  2196. X.IR E.g. ,
  2197. X.PP
  2198. X.RS
  2199. X.nf
  2200. X.ta 1i
  2201. X.ta 10m 20m 30m
  2202. Xharvard    .\s-1EDU\s0    # harvard is gateway to .EDU domain
  2203. X\&.\s-1EDU\s0    = {.\s-1BERKELEY\s0, .\s-1UMICH\s0}
  2204. X\&.\s-1BERKELEY\s0    = {ernie}
  2205. X.fi
  2206. X.RE
  2207. X.PP
  2208. Xyields
  2209. X.PP
  2210. X.RS
  2211. X.nf
  2212. X.ta 10m 20m
  2213. Xernie    ...!harvard!ernie.\s-1BERKELEY\s0.\s-1EDU\s0!%s
  2214. X.fi
  2215. X.RE
  2216. X.PP
  2217. XOutput is given for the nearest gateway
  2218. Xto a domain,
  2219. X.IR e.g. ,
  2220. Xthe example above gives
  2221. X.PP
  2222. X.RS
  2223. X.nf
  2224. X.ta 10m 25m
  2225. X\&.\s-1EDU\s0    ...!harvard!%s
  2226. X.fi
  2227. X.RE
  2228. X.PP
  2229. XOutput is given for a subdomain if it has a different
  2230. Xroute than its parent domain, or if all its ancestor domains are private.
  2231. X.PP
  2232. XIf the
  2233. X.B \-D
  2234. Xoption is given on the command line,
  2235. X.I pathalias
  2236. Xtreats a link from a domain to a host member of that domain as terminal.
  2237. XThis property extends to host members of subdomains,
  2238. X.IR etc ,
  2239. Xand discourages
  2240. Xroutes that use any domain member as a relay.
  2241. X.SS Databases
  2242. X.I Makedb
  2243. Xbuilds a
  2244. X.IR dbm (3)
  2245. Xdatabase from the standard input or from the named
  2246. X.IR files .
  2247. XInput is expected to be sequence of
  2248. X.SM ASCII
  2249. Xrecords,
  2250. Xeach consisting of a key field and a data field separated by a single tab.
  2251. XIf the tab is missing, the data field is assumed to be empty.
  2252. X.SH FILES ET AL.
  2253. X.ta \w'/usr/local/lib/palias.{dir,pag}     'u
  2254. X/usr/local/lib/palias.{dir,pag}    default dbm output
  2255. X.br
  2256. Xnewsgroup comp.mail.maps    likely location of some input files
  2257. X.br
  2258. X.IR getopt (3),
  2259. Xavailable from comp.sources.unix archives (if not in the C library).
  2260. X.SH BUGS
  2261. XThe
  2262. X.B \-i
  2263. Xoption should be the default.
  2264. X.PP
  2265. XThe order of arguments is significant.
  2266. XIn particular,
  2267. X.B \-i
  2268. Xand
  2269. X.B \-t
  2270. Xshould appear early.
  2271. X.PP
  2272. X.I Pathalias
  2273. Xcan generate hybrid (\fIi.e.\fP ambiguous) routes, which are
  2274. Xabhorrent and most certainly should not be given as examples
  2275. Xin the manual entry.
  2276. XExperienced mappers largely shun `@' when preparing input; this
  2277. Xis historical, but also reflects \s-1UUCP\s0's
  2278. Xfacile syntax for source routes.
  2279. X.PP
  2280. XMultiple `@'s in routes are loathsome, so
  2281. X.I pathalias
  2282. Xresorts to the ``magic %'' rule when necessary.
  2283. XThis convention is not documented anywhere, including here.
  2284. X.PP
  2285. XThe
  2286. X.B \-D
  2287. Xoption elides insignificant routes to domain members.
  2288. XThis is benign, perhaps even beneficial, but confusing, since the
  2289. Xbehavior is undocumented and somewhat unpredictable.
  2290. X.SH SEE ALSO
  2291. XP. Honeyman and S.M. Bellovin, ``\s-1PATHALIAS\s0 \fIor\fP The Care and Feeding
  2292. Xof Relative Addresses,''
  2293. Xin \fIProc. Summer \s-1USENIX\s0 Conf.\fP, Atlanta, 1986.
  2294. END_OF_FILE
  2295.   if test 12597 -ne `wc -c <'pathalias.8'`; then
  2296.     echo shar: \"'pathalias.8'\" unpacked with wrong size!
  2297.   fi
  2298.   # end of 'pathalias.8'
  2299. fi
  2300. echo shar: End of archive 1 \(of 3\).
  2301. cp /dev/null ark1isdone
  2302. MISSING=""
  2303. for I in 1 2 3 ; do
  2304.     if test ! -f ark${I}isdone ; then
  2305.     MISSING="${MISSING} ${I}"
  2306.     fi
  2307. done
  2308. if test "${MISSING}" = "" ; then
  2309.     echo You have unpacked all 3 archives.
  2310.     rm -f ark[1-9]isdone
  2311. else
  2312.     echo You still must unpack the following archives:
  2313.     echo "        " ${MISSING}
  2314. fi
  2315. exit 0
  2316. exit 0 # Just in case...
  2317.